﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace Farigola.Engine.PersistXml
{
    public class XmlUtils
    {
        //=====================================================================
        #region Write Xml element static methods. 

        //---------------------------------------------------------------------
        /// <summary>
        /// start create the types xmlDoc
        /// and add it to the xml document.
        /// </summary>
        /// <param name="xmlDoc"></param>
        public static void CreateEltXmlDeclaration(XmlDocument xmlDoc)
        {
            if (xmlDoc == null)
                return;

            XmlNode xmlNode = xmlDoc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
            xmlDoc.AppendChild(xmlNode);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create a xml element.
        /// Check params.
        /// Don't add it to the xml doc parent.
        /// </summary>
        /// <param name="xmldoc"></param>
        /// <param name="eltText"></param>
        /// <returns></returns>
        public static XmlElement CreateElt(XmlDocument xmldoc, bool addEltToDoc, string eltText)
        {
            if (xmldoc == null)
                return null;
            if (eltText == null)
                return null;

            try
            {
                XmlElement elt = xmldoc.CreateElement(eltText);

                if (addEltToDoc)
                    xmldoc.AppendChild(elt);
                return elt;
            }
            catch
            {
                return null;
            }
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create a xml element,
        /// don't add it to the xml document.
        /// </summary>
        /// <param name="xmldoc"></param>
        /// <param name="eltText"></param>
        /// <returns></returns>
        public static XmlElement CreateElt(XmlDocument xmldoc, string eltText)
        {
            return CreateElt(xmldoc, false, eltText);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create a xml element and add it to the xml document.
        /// </summary>
        /// <param name="xmldoc"></param>
        /// <param name="eltText"></param>
        /// <returns></returns>
        public static XmlElement CreateEltAdd(XmlDocument xmldoc, string eltText)
        {
            return CreateElt(xmldoc, true, eltText);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create a xml element and add it to the parent.
        /// </summary>
        /// <param name="xmldoc"></param>
        /// <param name="eltParent"></param>
        /// <param name="eltText"></param>
        /// <param name="innerText"></param>
        /// <returns></returns>
        public static XmlElement CreateEltAdd(XmlDocument xmldoc, XmlElement eltParent, string eltText, string innerText)
        {
            //if (xmldoc == null)
            //    return null;
            if (eltParent == null)
                return null;
            //if (eltText == null)
            //    return null;

            // create the xml element            
            //XmlElement elt = xmldoc.CreateElement(eltText);
            XmlElement elt = CreateElt(xmldoc, false, eltText);

            if(innerText!= null)
                elt.InnerText = innerText;

            eltParent.AppendChild(elt);
            return elt;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create a xml element and add it to the parent.
        /// </summary>
        /// <param name="xmldoc"></param>
        /// <param name="eltParent"></param>
        /// <param name="eltText"></param>
        /// <returns></returns>
        public static XmlElement CreateEltAdd(XmlDocument xmldoc, XmlElement eltParent, string eltText)
        {
            return CreateEltAdd(xmldoc, eltParent, eltText, null);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create an attribute and add it to the xml element.
        /// </summary>
        /// <param name="xmldoc"></param>
        /// <param name="eltParent"></param>
        /// <param name="attribName"></param>
        /// <param name="attribText"></param>
        /// <returns></returns>
        public static bool CreateAttribAdd(XmlDocument xmldoc, XmlElement elt, string attribName, string attribText)
        {
            if(xmldoc==null)
            return false;
            if(elt==null)
            return false;
            if (attribName == null)
                return false;
            if(attribText==null)
                return false;

            XmlAttribute xa = xmldoc.CreateAttribute(attribName);
            xa.Value = attribText;
            elt.Attributes.Append(xa);
            return true;
        }

        #endregion

        //=====================================================================
        #region Write Xml element static methods. 

        //---------------------------------------------------------------------
        /// <summary>
        /// Select a node child, and read the inner text.
        /// </summary>
        /// <param name="nodeParent"></param>
        /// <param name="nodeName"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public static bool SelectNodeText(XmlNode nodeParent, string nodeName, out string text)
        {
            text="";

            try
            {
                if (nodeParent == null)
                    return false;
                if (nodeName == null)
                    return false;

                XmlNode node = nodeParent.SelectSingleNode(nodeName);

                if (node.InnerText == null)
                    return false;

                text = node.InnerText;
                return true;
            }
            catch
            {
                return false;
            }
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Select a node child, and read the inner text.
        /// Convert this value to an int.
        /// </summary>
        /// <param name="nodeParent"></param>
        /// <param name="nodeName"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public static bool SelectNodeText(XmlNode nodeParent, string nodeName, out int value)
        {
            string str;
            value = 0;

            bool res = SelectNodeText(nodeParent, nodeName, out str);
            if (!res)
                return false;

            return int.TryParse(str, out value);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Select a node child, and read the inner text.
        /// Convert this value to a bool.
        /// </summary>
        /// <param name="nodeParent"></param>
        /// <param name="nodeName"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public static bool SelectNodeText(XmlNode nodeParent, string nodeName, out double value)
        {
            string str;
            value = 0.0;

            bool res = SelectNodeText(nodeParent, nodeName, out str);
            if (!res)
                return false;

            return double.TryParse(str, out value);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Select a node child, and read the inner text.
        /// Convert this value to a bool.
        /// </summary>
        /// <param name="nodeParent"></param>
        /// <param name="nodeName"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public static bool SelectNodeText(XmlNode nodeParent, string nodeName, out bool value)
        {
            string str;
            value = false;

            bool res = SelectNodeText(nodeParent, nodeName, out str);
            if (!res)
                return false;

            return bool.TryParse(str, out value);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Select the node child.
        /// </summary>
        /// <param name="nodeParent"></param>
        /// <param name="nodeName"></param>
        /// <param name="dateFormat"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool SelectNodeText(XmlNode nodeParent, string nodeName, string dateFormat, out DateTime value)
        {
            string str;
            value = DateTime.Now;

            try
            {
                bool res = SelectNodeText(nodeParent, nodeName, out str);
                if (!res)
                    return false;

                // decode the date
                value = DateTime.Now;
                DateTime dt = DateTime.ParseExact(str, dateFormat, null);

                return true;
            }
            catch
            {
                return false;
            }
        }


        //---------------------------------------------------------------------
        /// <summary>
        /// Read the attribute of the node (not the child).
        /// </summary>
        /// <param name="xmlNode"></param>
        /// <param name="attribName"></param>
        /// <param name="OnlyOneAttrib"></param>
        /// <param name="attribTypeValue"></param>
        /// <returns></returns>
        public static bool ReadNodeAttrib(XmlNode xmlNode, string attribName, bool checkOnlyOneAttrib, out string attribTypeValue)
        {
            attribTypeValue = "";

            try
            {
                if (xmlNode == null)
                    return false;

                if (checkOnlyOneAttrib)
                {
                    if (xmlNode.Attributes.Count != 1)
                        return false;
                }

                // read the attribute value
                attribTypeValue = xmlNode.Attributes[attribName].Value;
                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion


        //---------------------------------------------------------------------
        /// <summary>
        /// Remove the start and the end quote if present.
        /// 
        /// exp:  "bonjour"  -> bonjour
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static string RemoveStartEndQuote(string val)
        {
            //string valRes=val;
            if (val == null)
                return val;

            // wrong length, do nothing, return the string
            if (val.Length == 0 || val.Length == 1)
                return val;

            if (val.StartsWith("\"") || val.StartsWith("\'"))
                val = val.Substring(1);

            if (val.EndsWith("\"") || val.EndsWith("\'"))
                val = val.Remove(val.Length-1);

            return val;
        }

    }
}
